
local SPARKS_TEXTURE = resolvefilepath("images/hutao_sfx/butterfly_and_flame/sparks.tex")
local BUTTERFLY_TEXTURE = resolvefilepath("images/hutao_sfx/butterfly_and_flame/butterflies.tex")
local SMOKE_TEXTURE = resolvefilepath("images/hutao_sfx/butterfly_and_flame/smokes.tex")


local SHADER = "shaders/vfx_particle.ksh"

local COLOUR_ENVELOPE_NAME_SPARKS = "COLOUR_ENVELOPE_NAME_SPARKS_KIRBY"
local SCALE_ENVELOPE_NAME_SPARKS = "SCALE_ENVELOPE_NAME_SPARKS_KIRBY"

local COLOUR_ENVELOPE_NAME_BUTTERFLY = "COLOUR_ENVELOPE_NAME_BUTTERFLY_KIRBY"
local SCALE_ENVELOPE_NAME_BUTTERFLY = "SCALE_ENVELOPE_NAME_BUTTERFLY_KIRBY"

local COLOUR_ENVELOPE_NAME_SMOKE = "COLOUR_ENVELOPE_NAME_SMOKE_KIRBY"
local SCALE_ENVELOPE_NAME_SMOKE = "SCALE_ENVELOPE_NAME_SMOKE_KIRBY"

local assets =
{
    Asset("IMAGE", SPARKS_TEXTURE),
    Asset("IMAGE", BUTTERFLY_TEXTURE),
    Asset("IMAGE", SMOKE_TEXTURE),
    Asset("SHADER", SHADER),
}

--------------------------------------------------------------------------

local function IntColour(r, g, b, a)
    return { r / 255, g / 255, b / 255, a / 255 }
end
local function RandomVectorDelta(num)
    if num == nil or num == 0 then
        num = 1
    end
    local ret = math.random(num)
    if math.random(100) <= 50 then
        ret = -ret
    end
    return ret
end

--------------------------------------------------------------------------

local function InitEnvelope()
    -----------------------------------------------------------------------------
    -- sparks
        EnvelopeManager:AddColourEnvelope(
            COLOUR_ENVELOPE_NAME_SPARKS,
            {
                { 0,    IntColour(255, 255, 255, 0) },
                { 0.05,  IntColour(255, 255, 255, 200) },
                { 0.85,  IntColour(255, 255, 255, 200) },
                { 1,    IntColour(255, 255, 255, 0) },
            }
        )
    
        EnvelopeManager:AddVector2Envelope(
            SCALE_ENVELOPE_NAME_SPARKS,
            {
                { 0,    { 0.1, 0.1 } },
                { 0.5,  { 1, 1 } },
                { 0.8,  { 1, 1 } },
                { 1,    { 0.1, 0.1 } },
            }
        )
    -----------------------------------------------------------------------------
    -----------------------------------------------------------------------------
    -- butterfly
        EnvelopeManager:AddColourEnvelope(
            COLOUR_ENVELOPE_NAME_BUTTERFLY,
            {
                { 0,    IntColour(255, 255, 255, 0) },
                { 0.1,  IntColour(255, 255, 255, 200) },
                { 0.85,  IntColour(255, 255, 255, 200) },
                { 1,    IntColour(255, 255, 255, 0) },
            }
        )
        EnvelopeManager:AddVector2Envelope(
            SCALE_ENVELOPE_NAME_BUTTERFLY,
            {
                { 0,    { 0.2, 0.2 } },
                { 0.5,  { 1.5, 1.5 } },
                { 1,    { 1, 1 } },
            }
        )
    -----------------------------------------------------------------------------
    -----------------------------------------------------------------------------
    --- smoke
        EnvelopeManager:AddColourEnvelope(
            COLOUR_ENVELOPE_NAME_SMOKE,
            {
                { 0,    IntColour(255, 255, 255, .8) },
                { .2,   IntColour(255, 255, 255, 255) },
                { .7,   IntColour(255, 255, 255, 150) },
                { 1,    IntColour(255, 255, 0, 0) },
            }
        )

        EnvelopeManager:AddVector2Envelope(
            SCALE_ENVELOPE_NAME_SMOKE,
            {
                { 0,    { .5, .5 } },
                { .40,  { .3, .3 } },
                { .60,  { 6, 6 } },
                { .75,  { 4, 4 } },
                { 1,    { .1, .1 } },
            }
        )
    -----------------------------------------------------------------------------

    InitEnvelope = nil
    IntColour = nil
end
--------------------------------------------------------------------------------------------------------------------------------
----- sparks
local MAX_LIFETIME_SPARKS = 1
local MAX_NUM_SPARKS = 20
local function emit_fn_sparks (effect, emitter_fn)
    local vx, vy, vz = 0.006 * UnitRand() + 0.1   ,   0.2 + 0.006 * (UnitRand())   ,    0.006 * UnitRand() +0.1
    local lifetime =  MAX_LIFETIME_SPARKS* (.6 + math.random() * .4)
    local px, py, pz = emitter_fn()
    ----------------------------------------------
    --- -- 粒子随机方向 和速度偏移
    vx = vx*RandomVectorDelta()
    vy = vy*RandomVectorDelta(100)/100
    vz = vz*RandomVectorDelta()
    -----------------------------------------------
    ------- 粒子随机起始坐标
    px = px + RandomVectorDelta(4)/10
    px = px + math.random(100)/1000
    pz = pz + RandomVectorDelta(4)/10
    -----------------------------------------------

    local angle = 0
    local uv_offset = math.random(0, 7) * .125
    local ang_vel = 0

    effect:AddRotatingParticleUV(
        0,                  --  ----------------------  0号粒子发射器
        lifetime,           -- lifetime                 --- 生命周期
        px, py, pz,         -- position                 --- 坐标
        vx, vy, vz,         -- velocity                 --- 速度
        angle, ang_vel,     -- angle, angular_velocity  --- 角度  和  角速度
        uv_offset, 0        -- uv offset                --- 偏移  --- 不知道偏移什么
    )
end
--------------------------------------------------------------------------------------------------------------------------------
----- butterfly
local MAX_LIFETIME_BUTTERFLY = 1.3
local MAX_NUM_BUTTERFLY = 10
local function emit_fn_butterfly(effect, emitter_fn)
    local vx, vy, vz = ( 0.006 * UnitRand() + .05  ) , (  0.1 + 0.006 * (UnitRand())  ) , (   0.006 * UnitRand() +.05  )
    local lifetime = MAX_LIFETIME_BUTTERFLY * (.6 + math.random() * .4)
    local px, py, pz = emitter_fn()
    --- -- 粒子随机方向
    if math.random(100) <= 50 then
        vx = - vx
    end
    if math.random(100) <= 50 then
        vz = - vz
    end
    
    -- -----------------------------------------------
    ------- 粒子随机起始坐标
    local dx ,dz = RandomVectorDelta(5)/10,RandomVectorDelta(5)/10
    px = px + dx
    pz = pz + dz
    -- -----------------------------------------------

    local angle = 0
    local uv_offset = math.random(0, 7) * .125
    local ang_vel = RandomVectorDelta(10)/10

    effect:AddRotatingParticleUV(
        1,                  --  ----------------------  1号粒子发射器
        lifetime,           -- lifetime                 --- 生命周期
        px, py, pz,         -- position                 --- 坐标
        vx, vy, vz,         -- velocity                 --- 速度
        angle, ang_vel,     -- angle, angular_velocity  --- 角度  和  角速度
        uv_offset, 0        -- uv offset                --- 偏移  --- 不知道偏移什么
    )
end
--------------------------------------------------------------------------------------------------------------------------------
local MAX_LIFETIME_SMOKE = .75
local MAX_NUM_SMOKE = 6

local function emit_fn_smoke(effect, emitter_fn)
    local lifetime = MAX_LIFETIME_SMOKE * (.6 + math.random() * .4)
    local px, py, pz = emitter_fn()
    ----------------------------------------------
    --- -- 粒子速度方向
    local vx = 0
    local vz = 0

    local vy = ( 0.006 * (UnitRand()) +0.1 )*math.random(700,1000)/1000

    -- -----------------------------------------------
    ------- 粒子随机起始坐标
    px = px + RandomVectorDelta(5)/10
    -- py = py + math.random(500)/1000
    pz = pz + RandomVectorDelta(5)/10
    -- -----------------------------------------------

    -- -----------------------------------------------

    local angle = math.random() * 360
    local uv_offset = math.random(0, 7) * .125
    local ang_vel = RandomVectorDelta(10)/100

    effect:AddRotatingParticleUV(
        2,                  --  ----------------------  2 号粒子发射器
        lifetime,           -- lifetime                 --- 生命周期
        px, py, pz,         -- position                 --- 坐标
        vx, vy, vz,         -- velocity                 --- 速度
        angle, ang_vel,     -- angle, angular_velocity  --- 角度  和  角速度
        uv_offset, 0        -- uv offset                --- 偏移  --- 不知道偏移什么
    )
end
--------------------------------------------------------------------------------------------------------------------------------



local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddNetwork()

    inst:AddTag("FX")

    inst.entity:SetPristine()

    inst.persists = false

    --Dedicated server does not need to spawn local particle fx
    inst:DoTaskInTime(0.4,inst.Remove)

    if TheNet:IsDedicated() then
        return inst
    elseif InitEnvelope ~= nil then
        InitEnvelope()
    end

    local effect = inst.entity:AddVFXEffect()
    effect:InitEmitters(3)
    -----------------------------------------------------
    --Sparks
    -- effect:SetRenderResources(0, BUTTERFLY_TEXTURE, SHADER)
    effect:SetRenderResources(0, SPARKS_TEXTURE, SHADER)
    effect:SetRotationStatus(0, true)
    effect:SetGroundPhysics(0, false)   ----- 地面物理碰撞停留
    effect:SetUVFrameSize(0, .125, 1)
    effect:SetMaxNumParticles(0, MAX_NUM_SPARKS)
    effect:SetMaxLifetime(0,MAX_LIFETIME_SPARKS)
    effect:SetColourEnvelope(0, COLOUR_ENVELOPE_NAME_SPARKS)
    effect:SetScaleEnvelope(0, SCALE_ENVELOPE_NAME_SPARKS)
    -- effect:SetBlendMode(0, BLENDMODE.Premultiplied)
    effect:SetBlendMode(0, BLENDMODE.Additive)
    effect:EnableBloomPass(0, true) --------- tex发光发亮
    effect:SetSortOrder(0, 2)
    effect:SetSortOffset(0, 1)
    -----------------------------------------------------
    --butterfly
    effect:SetRenderResources(1, BUTTERFLY_TEXTURE, SHADER)
    effect:SetRotationStatus(1, true)
    effect:SetGroundPhysics(1, false)   ----- 地面物理碰撞停留
    effect:SetUVFrameSize(1, .125, 1)
    effect:SetMaxNumParticles(1, MAX_NUM_BUTTERFLY)
    effect:SetMaxLifetime(1, MAX_LIFETIME_BUTTERFLY)
    effect:SetColourEnvelope(1, COLOUR_ENVELOPE_NAME_BUTTERFLY)
    effect:SetScaleEnvelope(1, SCALE_ENVELOPE_NAME_BUTTERFLY)
    -- effect:SetBlendMode(1, BLENDMODE.Premultiplied)
    effect:SetBlendMode(1, BLENDMODE.Additive)
    effect:EnableBloomPass(1, true) --------- tex发光发亮
    effect:SetSortOrder(1, 1)
    effect:SetSortOffset(1, 1)
    -----------------------------------------------------

    --smoke
    effect:SetRenderResources(2, SMOKE_TEXTURE, SHADER)
    effect:SetRotationStatus(2, true)
    effect:SetGroundPhysics(2, false)   ----- 地面物理碰撞停留
    effect:SetUVFrameSize(2, .125, 1)
    effect:SetMaxNumParticles(2, MAX_NUM_SMOKE)
    effect:SetMaxLifetime(2, MAX_LIFETIME_SMOKE)
    effect:SetColourEnvelope(2, COLOUR_ENVELOPE_NAME_SMOKE)
    effect:SetScaleEnvelope(2, SCALE_ENVELOPE_NAME_SMOKE)
    -- effect:SetBlendMode(1, BLENDMODE.Premultiplied)
    effect:SetBlendMode(2, BLENDMODE.Additive)
    effect:EnableBloomPass(2, true) --------- tex发光发亮
    effect:SetSortOrder(2, 0)
    effect:SetSortOffset(2, 1)  ----- 用来设置是否可以挡住角色，0的时候不挡住

    -----------------------------------------------------

    -----------------------------------------------------

    local tick_time = TheSim:GetTickTime()

    local desired_pps_low = 3
    local desired_pps_high = 50
    local low_per_tick = desired_pps_low * tick_time
    local high_per_tick = desired_pps_high * tick_time

    local num_to_emit_SPARKS = 0
    local num_to_emit_BUTTERFLY = 0
    local num_to_emit_SMOKE = 0

    
    local emitter_fn = CreateBoxEmitter( -0.1, -0.3, -0.1, 0.1, 0.2, 0.1 )

    inst.last_pos = inst:GetPosition()

    EmitterManager:AddEmitter(inst, nil, function()
        ---------------------------------------------------------------------------
        -- SPARKS
        local dist_moved = inst:GetPosition() - inst.last_pos
        local move = dist_moved:Length()
        move = math.clamp(move*6, 0, 1)

        local per_tick = Lerp(low_per_tick, high_per_tick, move)

        inst.last_pos = inst:GetPosition()

        num_to_emit_SPARKS = num_to_emit_SPARKS + per_tick * math.random() * 3
        while num_to_emit_SPARKS > 1 do
            emit_fn_sparks(effect, emitter_fn)
            num_to_emit_SPARKS = num_to_emit_SPARKS - 1
        end
        ---------------------------------------------------------------------------
        ------- butterfly
        num_to_emit_BUTTERFLY = num_to_emit_BUTTERFLY + per_tick * math.random() * 3
        while num_to_emit_BUTTERFLY > 1 do
            emit_fn_butterfly(effect, emitter_fn)
            num_to_emit_BUTTERFLY = num_to_emit_BUTTERFLY - 1
        end

        ---------------------------------------------------------------------------
        ------- smoke  
        num_to_emit_SMOKE = num_to_emit_SMOKE + per_tick * math.random() * 3
        while num_to_emit_SMOKE > 1 do
            emit_fn_smoke(effect, emitter_fn)
            num_to_emit_SMOKE = num_to_emit_SMOKE - 1
        end
        ---------------------------------------------------------------------------
    end)

    return inst
end

return Prefab("hutao_sfx_butterflies_and_flames", fn, assets)
